﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BaseCardTypes = Wormhole.Engine.CardLibrary.BaseCardTypes;
using CardTypes = Wormhole.Engine.CardLibrary.CardTypes;

namespace Wormhole.Engine.Decks
{
	/// <author>Rodney McKay</author>
	/// <date>10 April 2008</date>
	/// <summary>
	/// The base class for decks that can hold cards that can be assigned to a mission.
	/// </summary>
	public class SkillCards : Deck
	{
		#region Delegates
		/// <summary>
		/// The delegate for the assign allowed event.
		/// </summary>
		/// <param name="cards">A collection of cards that may be played from the hand.</param>
		public delegate void AssignAllowedDelegate(Deck cards);

		/// <summary>
		/// The delegate for the event that is raised to indicate that the player may not assign cards to the mission.
		/// </summary>
		public delegate void AssignDisallowedDelegate();
		#endregion

		#region Events
		/// <summary>
		/// When a card is assigned this event is raised.
		/// </summary>
		public event BaseCardTypes.SkillsCard.CardAssignedDelegate CardAssigned;

		/// <summary>
		/// This event is raised when a card is unassigned.
		/// </summary>
		public event BaseCardTypes.SkillsCard.CardAssignedDelegate CardUnassigned;

		/// <summary>
		/// This event is raised when the player is allowed to assign a card to the current mission.
		/// </summary>
		public event AssignAllowedDelegate AssignAllowed;

		/// <summary>
		/// This event is raised when the player is not allowed to assign cards to the current mission.
		/// </summary>
		public event AssignDisallowedDelegate AssignDisallowed;
		#endregion

		#region Properties

		#region Allow Assign
		private bool _allowAssign = false;
		/// <summary>
		/// Is the player allowed to assign cards to the current mission?
		/// </summary>
		public bool AllowAssign
		{
			get
			{
				return this._allowAssign;
			}
		}
		#endregion

		#endregion

		#region Constructor
		/// <summary>
		/// Initialize a default instance of the class.
		/// </summary>
		public SkillCards() : base()
		{
		}

		/// <summary>
		/// Create a new deck for a specific player.
		/// </summary>
		/// <param name="player">The player the deck belongs to.</param>
		public SkillCards(Player.Player player)
			: base(player)
		{
		}
		#endregion	

		#region Set Allow Assign
		/// <summary>
		/// Set the allow assign property and raise the appropriate event.
		/// </summary>
		/// <param name="allow">Should the player be allowed to assign cards to the mission.</param>
		public void SetAllowAssign(bool allow)
		{
			this._allowAssign = allow;

			// set the indivudial cards
			foreach (BaseCardTypes.Card card in this)
			{
				if (allow)
					card.InputStatus = BaseCardTypes.InputStatus.AllowAssign;
				else
					card.InputStatus = BaseCardTypes.InputStatus.Unavailable;
			}

			if (allow)
				this.OnAssignAllowed();
			else
				this.OnAssignDisallowed();
		}
		#endregion

		#region Set Player Events
		/// <summary>
		/// Wire up the events from other engine objects to listen for.
		/// </summary>
		protected override void SetEngineEvents()
		{
			this.Player.Game.Mission.MissionPlayed += new Mission.Mission.MissionPlayedDelegate(Mission_MissionPlayed);
		}
		#endregion

		#region Add
		/// <summary>
		/// Add a card to the deck and wire up events for the card.
		/// </summary>
		/// <param name="card">The card that should be added.</param>
		public override void Add(BaseCardTypes.Card card)
		{
			// add the card
			base.Add(card);

			// set the card status
			if (this.AllowAssign)
				card.InputStatus = BaseCardTypes.InputStatus.AllowAssign;
			else
				card.InputStatus = BaseCardTypes.InputStatus.Unavailable;

			// wire up the card events
			BaseCardTypes.SkillsCard skillsCard = card as BaseCardTypes.SkillsCard;
			if (skillsCard != null)
			{
				skillsCard.CardAssigned += new Wormhole.Engine.CardLibrary.BaseCardTypes.SkillsCard.CardAssignedDelegate(skillsCard_CardAssigned);
				skillsCard.CardUnassigned += new Wormhole.Engine.CardLibrary.BaseCardTypes.SkillsCard.CardAssignedDelegate(skillsCard_CardUnassigned);
			}
		}
		#endregion

		#region Event Handlers

		#region Card Assigned
		/// <summary>
		/// Handle the card assigned event of a team card.
		/// </summary>
		/// <param name="card">The card that was assigned.</param>
		private void skillsCard_CardAssigned(Wormhole.Engine.CardLibrary.BaseCardTypes.SkillsCard card)
		{
			this.OnCardAssigned(card);
		}
		#endregion

		#region Card Unassigned
		/// <summary>
		/// Handle the event when a card is unassigned.
		/// </summary>
		/// <param name="card">The card that was unassigned.</param>
		private void skillsCard_CardUnassigned(Wormhole.Engine.CardLibrary.BaseCardTypes.SkillsCard card)
		{
			this.OnCardUnassigned(card);
		}
		#endregion

		#region Mission Played
		/// <summary>
		/// When a mission is played update the cards that can be assigned.
		/// </summary>
		void Mission_MissionPlayed()
		{
			if (this.AllowAssign)
				this.OnAssignAllowed();
			else
				this.OnAssignDisallowed();
		}
		#endregion

		#endregion

		#region On Card Assigned
		/// <summary>
		/// Raise the card assigned event.
		/// </summary>
		/// <param name="card">The card that was assigned.</param>
		protected void OnCardAssigned(BaseCardTypes.SkillsCard card)
		{
			if (this.CardAssigned != null)
				this.CardAssigned(card);
		}
		#endregion

		#region On Card Unassigned
		/// <summary>
		/// Raise the card unassigned event.
		/// </summary>
		/// <param name="card">The card that was unassigned.</param>
		protected void OnCardUnassigned(BaseCardTypes.SkillsCard card)
		{
			if (this.CardUnassigned != null)
				this.CardUnassigned(card);
		}
		#endregion

		#region On Assign Allowed
		/// <summary>
		/// Get the cards that the player may assign to the current mission.
		/// </summary>
		protected void OnAssignAllowed()
		{
			if (this.AssignAllowed != null)
			{
				Deck allowedCards = this.GetAssignableCards();
				this.AssignAllowed(allowedCards);
			}
		}
		#endregion

		#region On Assign Disallowed
		/// <summary>
		/// Raise the assign disallowed event.
		/// </summary>
		protected void OnAssignDisallowed()
		{
			if (this.AssignDisallowed != null)
				this.AssignDisallowed();
		}
		#endregion

		#region Get Assignable Cards
		/// <summary>
		/// Get a list of cards that the player may assign to a mission.
		/// </summary>
		/// <returns>A collection of cards that may be assigned to the current mission.</returns>
		protected Decks.Deck GetAssignableCards()
		{
			Decks.Deck deck = new Decks.Deck();

			foreach (BaseCardTypes.Card card in this)
			{
				CardTypes.Character teamCard = card as CardTypes.Character;
				if (teamCard != null)
				{
					if (teamCard.CanAssign())
						deck.Add(card);
				}
			}

			return deck;
		}
		#endregion
	}
}
